package org.ruslan.kolobok;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import org.ruslan.kolobok.model.Barrel;
import org.ruslan.kolobok.model.Barrel.BarrelState;
import org.ruslan.kolobok.model.BarrelType;
import org.ruslan.kolobok.model.LevelObject;
import org.ruslan.kolobok.model.Soldier;
import org.ruslan.kolobok.model.Soldier.SoldierState;
import org.ruslan.kolobok.model.SoldierType;
import org.ruslan.kolobok.model.Type;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.ObjectMap;

public class Level implements ILevel {

	// List
	private static <T extends Type> ObjectMap<String, T> readFile(FileHandle file, Class<T[]> arrayClass) {
		ObjectMap<String, T> map = new ObjectMap<String, T>();
		Json json = new Json();
		T[] entries = json.fromJson(arrayClass, file);
		for (T entry : entries) {
			map.put(entry.getName(), entry);
		}
		return map;
	}

	private ObjectMap<String, ? extends Type> soldierTypes;
	private ObjectMap<String, ? extends Type> objectTypes;
	private final List<Soldier> soldiers;
	private final List<Barrel> barrels;
	private final List<LevelObject<Type>> hittables;
	public float maxX = 8000;
	public float maxY = 1000;
	public float maxZ = 1000;

	public Level() {
		soldierTypes = readFile(Gdx.files.internal("data/enemies.json"), SoldierType[].class);
		objectTypes = readFile(Gdx.files.internal("data/objects.json"), BarrelType[].class);
		soldiers = new LinkedList<Soldier>();
		barrels = new LinkedList<Barrel>();
		hittables = new LinkedList<LevelObject<Type>>();

		generateLevel();
	}

	public List<Soldier> getSoldiers() {
		// for (ObjectMap.Entry<String,SoldierType> entry : objects.entries()) {
		// AliveLevelObject<SoldierType> soldier = new
		// AliveLevelObject<SoldierType>(entry.value);
		// soldiers.add(soldier);
		// }
		return soldiers;
	}

	public List<Barrel> getBarrels() {
		return barrels;
	}

	private void generateLevel() {
		Type type = soldierTypes.get("soldier");
//		float z = -1000;
		for (int i = 0; i < 10; i++) {
			float x = (float) Math.random() * maxX;
			 float z = (float) Math.random() * -maxZ;
//			z += 60;
			System.out.println(z);
			// Soldier soldier = new Soldier(x, 0, z);
			Soldier soldier = new Soldier((SoldierType) type);
			soldier.setActive(true);
			soldier.setState(SoldierState.WALK);
			soldier.getPosition().set(x, 0, z);
			soldiers.add(soldier);
		}

		type = soldierTypes.get("btr");
		for (int i = 0; i < 5; i++) {
			float x = (float) Math.random() * maxX;
			float z = (float) Math.random() * -maxZ;
//			z += 60;
			System.out.println(z);
			// Soldier soldier = new Soldier(x, 0, z);
			Soldier soldier = new Soldier((SoldierType) type);
			soldier.setActive(true);
			soldier.setState(SoldierState.WALK);
			soldier.getPosition().set(x, 0, z);
			soldiers.add(soldier);
		}

		type = objectTypes.get("barrel");
		for (int i = 0; i < 40; i++) {
			float x = (float) Math.random() * maxX;
			float z = (float) Math.random() * -maxZ;
//			z += 60;
			System.out.println(z);
			Barrel barrel = new Barrel(type);
			barrel.getPosition().set(x, 0, z);
			barrel.setState(BarrelState.STILL);
			barrel.setActive(true);
			barrels.add(barrel);
		}

		hittables.addAll(soldiers);
		hittables.addAll(barrels);
		Collections.sort(hittables, new Comparator<LevelObject<Type>>() {

			@Override
			public int compare(LevelObject<Type> o1, LevelObject<Type> o2) {
				float d = o2.getPosition().z - o1.getPosition().z;
				if (d > 0) {
					return 1;
				} else if (d < 0) {
					return -1;
				}

				return 0;
			}
		});

		// Soldier soldier = new Soldier(100, 0, -100);
		// soldiers.add(soldier);
	}

	@Override
	public float getWidth() {
		return maxX;
	}

	public List<LevelObject<Type>> getHittables() {
		return hittables;
	}

	// MonsterType monsterType = typeStore.get("skeleton", Class<MonsterType>
	// monsterType);
}
